package trading.formulas.functions;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import trading.Parameters;
import trading.data.Controller;
import trading.data.IDataType;
import trading.data.IStockTickDataCollection;


public class EMA implements IFunction{

	/**
	 * parameters : cycle 
	 */
	private Parameters PARAM = new Parameters(new int[][]{{100,1,5,1}});
	
	/**
	 * for performance issue, we hold the ema data in map.
	 * key name + "_" + type;  
	 */
	private static Map<String, IStockTickDataCollection> emaDataMap = new HashMap<String, IStockTickDataCollection>();  
	
	final public static int CYCLE_IDX = 0; 
	
	public static EMA getEMAInstance()
	{
		return new EMA();
	}
	
	private EMA(){}
	
	private float getValue(IStockTickDataCollection dataCollection, String type, int index, int cycle, IDataFunctionProvider provider)
	{
		String emaType = Controller.getDatatypeName(this, type, provider);
		float result = Controller.getValueOn(dataCollection, index, emaType);
		if(result == Float.MIN_VALUE)
		{
			float x = provider.getValue(type, dataCollection, index);
			if(index == 0)
			{
				result = x;
			}
			else
			{
				result = (2 * x + (cycle -1) * getValue(dataCollection, type, index - 1, cycle, provider))/(cycle + 1);
				Controller.setValueOn(dataCollection, index, emaType, result);
			}
		}
		return result;
	}

	@Override
	public Parameters getParameters() {
		return PARAM;
	}
	
	@Override
	public String getName() {
		return "EMA";
	}

	@Override
	public float getValue(String datatype, IStockTickDataCollection dataCollection, int index) throws TradingFunctionException 
	{
		return getValue(datatype, dataCollection, index, BasicFunctionProvider.INSTANCE);
	}
	

	@Override
	public float getValue(String datatype, IStockTickDataCollection dataCollection, int index,
			IDataFunctionProvider provider) {

		int cycle = getParameters().getParamValue(CYCLE_IDX);
		return getValue(dataCollection, datatype, index, cycle, provider);
	}
	
	public static void main(String[] args) {
		Calendar cal = Controller.createZeroCaledar();
		cal.set(2006, 05 - 1, 15);
		IStockTickDataCollection dataCollection = Controller.getTickData();
		int index = Controller.getIndex(dataCollection, cal, true);
		System.out.println(index);
//		index = 10;
		EMA ema = EMA.getEMAInstance();
		Parameters params = ema.getParameters();
		params.setParamValue( CYCLE_IDX , 7);
		System.out.println(Math.abs(ema.getValue(IDataType.CLOSE_NAME, dataCollection, index ) - 1.251)<0.001);
	}

}
